
package com.example.quicklaunch;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.TouchDelegate;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.EditText;
import android.widget.ImageButton;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.util.ArrayList;
import java.util.List;

public class MainActivity extends Activity implements OnClickListener, OnLongClickListener {
    private ProgressBar mProgressDialog;
    private final int MSG_DISSMISSDIALOG = 1;
    private final int MSG_FLUSH_LIST = 2;
    private final int[] IDS = new int[] {
            R.id.one, R.id.two, R.id.three,
            R.id.four, R.id.five, R.id.six, R.id.seven, R.id.eight, R.id.nine, R.id.zero
    };
    private TextView mEditText;
    private ListView mListView;
    private IAllAppListService mService;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mEditText = (TextView) findViewById(R.id.input);
        mProgressDialog = (ProgressBar) findViewById(R.id.progress);
        mListView = (ListView) findViewById(R.id.list);
        mListView.setAdapter(new AppListAdapter(this));
        mEditText.addTextChangedListener(new TextWatcher() {

            @Override
            public void onTextChanged(CharSequence s, int start, int before,
                    int count) {
                // Do nothing
            }

            @Override
            public void beforeTextChanged(CharSequence s, int start, int count,
                    int after) {
                // Do nothing
            }

            @Override
            public void afterTextChanged(Editable s) {
                if (TextUtils.isEmpty(s.toString())) {
                    showAllAppList();
                } else {
                    if (mService != null) {
                        try {
                            List<AppItem> items = mService.getMatched(s.toString());
                            // Set values and flush ListView
                            ((AppListAdapter) mListView.getAdapter()).setValue(items);
                            // return to head.
                            mListView.setSelection(0);
                        } catch (RemoteException e) {
                            MLog.e("remote exception");
                            e.printStackTrace();
                        }
                    }
                }
            }
        });

        for (int id : IDS) {
            findViewById(id).setOnClickListener(this);
        }
        ImageButton deleteButton = (ImageButton) findViewById(R.id.delete);
        deleteButton.setOnClickListener(this);
        deleteButton.setOnLongClickListener(this);
        expandViewTouchDelegate(deleteButton);

        mListView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> item, View view, int index,
                    long id) {
                AppItem appItem = (AppItem) mListView.getAdapter().getItem(
                        index);
                Intent intent = new Intent(Intent.ACTION_MAIN);
                intent.setClassName(appItem.getAppPackage(),
                        appItem.getAppClassName());
                intent.addCategory(Intent.CATEGORY_LAUNCHER);
                intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK
                        | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
                startActivity(intent);
                MainActivity.this.finish();
            }
        });
        handler.post(mServiceStartRunnable);
    }

    private Runnable mServiceStartRunnable = new Runnable() {
        @Override
        public void run() {
            Intent serviceIntent = AllAppListService.createInitServiceIntent(MainActivity.this,
                    false);
            startService(serviceIntent);
            bindService(serviceIntent, mConnection, BIND_NOT_FOREGROUND);
        }
    };

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceDisconnected(ComponentName name) {
            mService = null;
        }
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mService = IAllAppListService.Stub.asInterface(service);
            try {
                mService.registerCallback(mCallBack);
                mService.init(false);
            } catch (RemoteException e) {
                MLog.e("remote exception");
                e.printStackTrace();
            }
        }
    };
    /**
     * 扩大View的触摸和点击响应范围,最大不超过其父View范围
     * 
     * @param view
     * @param top
     * @param bottom
     * @param left
     * @param right
     */
    private void expandViewTouchDelegate(final View view) {
        ((View) view.getParent()).post(new Runnable() {
            @Override
            public void run() {
                Rect bounds = new Rect();
                view.setEnabled(true);
                view.getHitRect(bounds);
                bounds.right += 45;
                TouchDelegate touchDelegate = new TouchDelegate(bounds, view);
                if (View.class.isInstance(view.getParent())) {
                    ((View) view.getParent()).setTouchDelegate(touchDelegate);
                }
            }
        });
    }

    @SuppressWarnings("unchecked")
    private void showAllAppList() {
        try {
            if (mListView.getVisibility() != View.VISIBLE) {
                mListView.setVisibility(View.VISIBLE);
            }
            List<AppItem> items = new ArrayList<AppItem>();
            items.addAll(mService.allItems().values());
            for (AppItem item : items) {
                item.clearMatchedIndex();
            }
            ((AppListAdapter) mListView.getAdapter()).setValue(items);
            // return to head.
            mListView.setSelection(0);
        } catch (RemoteException e) {
            MLog.e("remote exception");
            e.printStackTrace();
        }
    }

    Handler handler = new Handler() {
        public void handleMessage(android.os.Message msg) {
            int what = msg.what;
            MLog.d("handleMessage msg = " + what);
            switch (what) {
                case MSG_DISSMISSDIALOG:
                    if (mProgressDialog.getVisibility() == View.VISIBLE) {
                        mProgressDialog.setVisibility(View.GONE);
                    }
                    showAllAppList();
                    break;
                case MSG_FLUSH_LIST:
                    if (mEditText != null) {
                        mEditText.setText("");
                    }
                    break;
                default:
                    break;
            }

        };
    };

    protected void onStart() {
        super.onStart();
        mProgressDialog.setVisibility(View.VISIBLE);
        mListView.setVisibility(View.GONE);
        if (mService != null) {
            try {
                mService.init(false);
            } catch (RemoteException e) {
                MLog.e("remote exception");
                e.printStackTrace();
            }
        }
    };

    @Override
    protected void onStop() {
        super.onStop();
        mEditText.setText("");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(mConnection);
        if (mService != null) {
            try {
                mService.unregisterCallback(mCallBack);
            } catch (RemoteException e) {
                MLog.e("remote exception");
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onClick(View v) {
        int id = v.getId();
        String keyCode;
        switch (id) {
            case R.id.two:
                keyCode = "2";
                break;
            case R.id.three:
                keyCode = "3";
                break;
            case R.id.four:
                keyCode = "4";
                break;
            case R.id.five:
                keyCode = "5";
                break;
            case R.id.six:
                keyCode = "6";
                break;
            case R.id.seven:
                keyCode = "7";
                break;
            case R.id.eight:
                keyCode = "8";
                break;
            case R.id.nine:
                keyCode = "9";
                break;
            case R.id.one:
                keyCode = "1";
                break;
            case R.id.zero:
                keyCode = "0";
                break;
            case R.id.delete:
                String text = mEditText.getText().toString();
                if (!TextUtils.isEmpty(text)) {
                    String newText = text.substring(0, text.length() - 1);
                    mEditText.setText(newText);
                }
                return;
            default:
                return;
        }
        mEditText.append(keyCode);
    }

    @Override
    public boolean onLongClick(View v) {
        mEditText.setText("");
        return true;
    }

    private IServiceCallBack mCallBack = new IServiceCallBack.Stub() {
        @Override
        public void onLoadFinish() throws RemoteException {
            handler.sendEmptyMessage(MSG_DISSMISSDIALOG);
        }

        @Override
        public void onDataChanged() throws RemoteException {
            handler.sendEmptyMessage(MSG_FLUSH_LIST);
        }
    };
}
